package cl.ncx.cmvrc.utils;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.ejb.EJBHome;
import javax.ejb.HomeHandle;
import javax.rmi.PortableRemoteObject;
import java.util.HashMap;
import java.rmi.RemoteException;

public class ServiceLocator {

	private static ServiceLocator instance;
	 private HashMap<String, HomeHandle> cache;
	 private Context context;
	 
	 // return the singelton service locator       
	 public static ServiceLocator getInstance()	 {
	  if (instance == null)
	   instance = new ServiceLocator();
	  
	  return instance;
	 }
	    
	 // Creates a new instance of ServiceLocator
	 private ServiceLocator()  {
	  cache = new HashMap<String, HomeHandle>();
	  try {
		context = new InitialContext();
	} catch (NamingException e) {
		e.printStackTrace();
	}
	 
	 }
	 
	 // get an EJB from the cache or directory service   
	 public EJBHome getRemoteEJB(String name, Class<?> type) {
	  // see if it's in the cache
	  if (cache.containsKey(name)) {
	   // cache HomeHandle objects since they are maintained
	   // by the container
	   HomeHandle hh = (HomeHandle)cache.get(name);
	            
	  
	    try {
			return hh.getEJBHome();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	
	  }
	  
	  // access to the shared context as well as modifications
	  // to the HashMap must be synchronized.  Hopefully the
	  // majority of cases are handled above     
	  synchronized(this) {
	  
	    Object rRef = null;
		try {
			rRef = context.lookup(name);
		} catch (NamingException e) {
			e.printStackTrace();
		}
	    EJBHome eh = (EJBHome)PortableRemoteObject.narrow(rRef, type);
	    
	    try {
			cache.put(name, eh.getHomeHandle());
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	    return eh;
	  
	  }
	 }
}
